home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 8: LINUX Games
/
Linux Cubed Series 8 - LINUX Games.iso
/
games
/
x11
/
rpg
/
crossfir.92
/
crossfir
/
crossfire-0.92.5
/
common
/
loader.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-07-24
|
29KB
|
999 lines
/*
* static char *rcsid_object_c =
* "$Id: loader.c,v 1.33 1996/07/24 07:03:10 master Exp master $";
*/
/*
CrossFire, A Multiplayer game for X-windows
Copyright (C) 1994 Mark Wedel
Copyright (C) 1992 Frank Tore Johansen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author can be reached via e-mail to master@rahul.net
*/
/* Eneq(@csd.uu.se): Added weight-modifiers in environment of objects.
sub/add_weight will transcend the environment updating the carrying
variable. */
#include <global.h>
#include <loader.h>
/* All the variable names. Each entry should correspond to the
* V_ vlaue in loader.h (that is, the 20'th value in this array should
* correspond to the 20'th V_(value) in loader.h)
*/
/* If you change this list (add/delete/rename), also update the list
* in crossedit/Attr.c, around line 360. That list is the variables
* that can be set in crossedit for various objects.
*/
static char *variable_const[NR_OF_VARIABLES] = {
"Object","name","race","slaying","msg","endmsg",
"Inventory","arch","other_arch","More",
"anim","mina","end","last_heal","last_sp","last_eat",
"speed","speed_left","slow_move",
"face","Str","Dex","Con","Wis","Cha","Int","Pow","hp","maxhp","sp","maxsp",
"grace","maxgrace",
"exp","food","dam","wc","ac","x","y","nrof","level","direction",
"type","material","value", "weight","carrying",
"immune","protected","attacktype","vulnerable",
"path_attuned","path_repelled","path_denied",
"invisible","magic","state","alive","applied","unpaid","need_an","need_ie",
"no_pick","no_pass","walk_on","walk_off","fly_on","fly_off","is_animated",
"flying","monster", "friendly","generator","auto_apply","treasure",
"apply_once","see_invisible","can_roll","is_turning","is_turnable",
"is_used_up","identified","reflecting","changing","splitting","hitback",
"startequip","blocksview","editable","undead","scared","unaggressive",
"color_fg","color_bg","reflect_missile","reflect_spell","no_magic",
"wiz","was_wiz","no_fix_player","tear_down", "luck", "run_away","pass_thru",
"can_pass_thru","pick_up","anim_speed","container","no_drop",
"no_pretext","will_apply","random_movement", "can_apply",
"can_cast_spell","can_use_scroll","can_use_wand","can_use_bow",
"can_use_armour","can_use_weapon","can_use_ring","has_ready_wand",
"has_ready_bow","xrays","is_floor","lifesave","no_strength",
"sleep","stand_still","random_move","only_attack","armour",
"attack_movement","move_state","confused","stealth","connected",
"cursed","damned","see_anywhere","known_magical","known_cursed",
"can_steal","been_applied","title","has_ready_rod","can_use_rod",
"has_ready_horn","can_use_horn","expmul",
"unique","make_invisible","inv_locked",
"is_wooded","is_hilly","has_ready_skill","has_ready_weapon",
"no_skill_ident","glow_radius","is_blind","can_see_in_dark",
"is_cauldron",
#ifdef NPC_PROG
"npc_status","npc_program",
#endif
};
char *variables[NR_OF_VARIABLES];
/* This array equates the FLAG_ values with the V_ values. Use -1 to
* put gaps in the array that should no be processed.
* The order matches the order of the define values in 'define.h'.
*/
int flag_links[NUM_FLAGS+1][2] ={
{FLAG_ALIVE, V_ALIVE}, {FLAG_WIZ, V_WIZ},
{-1, -1}, {-1, -1}, /* REMOVED and FREED flags */
{FLAG_WAS_WIZ, V_WAS_WIZ}, {FLAG_APPLIED, V_APPLIED},
{FLAG_UNPAID, V_UNPAID}, {FLAG_AN, V_NEED_AN},
{FLAG_NO_PICK, V_NO_PICK}, {FLAG_WALK_ON, V_WALK_ON},
{FLAG_NO_PASS, V_NO_PASS},{FLAG_ANIMATE, V_IS_ANIMATED},
{FLAG_SLOW_MOVE, -1}, {FLAG_FLYING, V_FLYING},
{FLAG_MONSTER, V_MONSTER}, {FLAG_FRIENDLY, V_FRIENDLY},
{FLAG_GENERATOR, V_GENERATOR}, {-1, -1}, /* FLAG_THROWN */
{FLAG_AUTO_APPLY, V_AUTO_APPLY}, {FLAG_TREASURE, V_TREASURE},
{FLAG_APPLY_ONCE, V_APPLY_ONCE},{FLAG_SEE_INVISIBLE, V_SEE_INVISIBLE},
{FLAG_CAN_ROLL, V_CAN_ROLL}, {FLAG_IS_TURNING, V_IS_TURNING},
{FLAG_IS_TURNABLE, V_IS_TURNABLE},{FLAG_WALK_OFF, V_WALK_OFF},
{FLAG_FLY_ON, V_FLY_ON},{FLAG_FLY_OFF, V_FLY_OFF},
{FLAG_IS_USED_UP, V_IS_USED_UP}, {FLAG_IDENTIFIED, V_IDENTIFIED},
{FLAG_REFLECTING, V_REFLECTING}, {FLAG_CHANGING, V_CHANGING},
{FLAG_SPLITTING, V_SPLITTING}, {FLAG_HITBACK, V_HITBACK},
{FLAG_STARTEQUIP, V_STARTEQUIP}, {FLAG_BLOCKSVIEW, V_BLOCKSVIEW},
{FLAG_UNDEAD, V_UNDEAD}, {FLAG_SCARED, V_SCARED},
{FLAG_UNAGGRESSIVE, V_UNAGGRESSIVE}, {FLAG_REFL_MISSILE, V_REFLECT_MISSILE},
{FLAG_REFL_SPELL, V_REFLECT_SPELL}, {FLAG_NO_MAGIC, V_NO_MAGIC},
{FLAG_NO_FIX_PLAYER, V_NO_FIX_PLAYER}, {FLAG_NEED_IE, V_NEED_IE},
{FLAG_TEAR_DOWN, V_TEAR_DOWN}, {FLAG_RUN_AWAY, V_RUN_AWAY},
{FLAG_PASS_THRU, V_PASS_THRU}, {FLAG_CAN_PASS_THRU, V_CAN_PASS_THRU},
{FLAG_PICK_UP, V_PICK_UP}, {FLAG_UNIQUE, V_UNIQUE},
{FLAG_NO_DROP, V_NO_DROP}, {FLAG_NO_PRETEXT, V_NO_PRETEXT},
{FLAG_CAST_SPELL, V_CAN_CAST_SPELL}, {FLAG_USE_SCROLL, V_CAN_USE_SCROLL},
{FLAG_USE_WAND, V_CAN_USE_WAND},{FLAG_USE_BOW, V_CAN_USE_BOW},
{FLAG_USE_ARMOUR, V_CAN_USE_ARMOUR},{FLAG_USE_WEAPON, V_CAN_USE_WEAPON},
{FLAG_USE_RING, V_CAN_USE_RING}, {FLAG_READY_WAND, V_HAS_READY_WAND},
{FLAG_READY_BOW, V_HAS_READY_BOW}, {FLAG_XRAYS, V_XRAYS},
{-1, -1 /*NO_APPLY*/}, {FLAG_IS_FLOOR, V_IS_FLOOR},
{FLAG_LIFESAVE, V_LIFESAVE}, {FLAG_NO_STRENGTH, V_NO_STRENGTH},
{FLAG_SLEEP, V_SLEEP}, {FLAG_STAND_STILL, V_STAND_STILL},
{FLAG_RANDOM_MOVE, V_RANDOM_MOVEMENT}, {FLAG_ONLY_ATTACK, V_ONLY_ATTACK},
{FLAG_CONFUSED, V_CONFUSED}, {FLAG_STEALTH, V_STEALTH},
{-1, -1 /*WIZPASS*/}, {-1, -1 /*IS_LINKED */},
{FLAG_CURSED, V_CURSED}, {FLAG_DAMNED, V_DAMNED},
{FLAG_SEE_ANYWHERE, V_SEE_ANYWHERE}, {FLAG_KNOWN_MAGICAL, V_KNOWN_MAGICAL},
{FLAG_KNOWN_CURSED, V_KNOWN_CURSED}, {FLAG_CAN_STEAL, V_CAN_STEAL},
{FLAG_BEEN_APPLIED, V_BEEN_APPLIED}, {FLAG_READY_ROD, V_HAS_READY_ROD},
{FLAG_USE_ROD, V_CAN_USE_ROD}, {FLAG_READY_HORN, V_HAS_READY_HORN},
{FLAG_USE_HORN, V_CAN_USE_HORN},{FLAG_MAKE_INVIS,V_MAKE_INVIS},
{FLAG_INV_LOCKED,V_INV_LOCKED},{FLAG_IS_WOODED,V_IS_WOODED},
{FLAG_IS_HILLY,V_IS_HILLY},{FLAG_READY_SKILL,V_HAS_READY_SKILL},
{FLAG_READY_WEAPON,V_HAS_READY_WEAPON},{FLAG_NO_SKILL_IDENT,V_NO_SKILL_IDENT},
{FLAG_BLIND,V_BLIND},{FLAG_SEE_IN_DARK,V_SEE_IN_DARK},
{FLAG_IS_CAULDRON,V_IS_CAULDRON}
};
void save_double(char *buf,char *name,double v)
{
char tbuf[200];
sprintf(tbuf,"%s %f\n",name,v);
strcat(buf,tbuf);
}
/*
* Initialises the array of variable-names. Needed before any
* objects can be loaded. Called by init_library().
*/
void init_vars() {
int i;
for(i=0;i<NR_OF_VARIABLES;i++)
variables[i]=add_string(variable_const[i]);
}
/*
* Searches through all possible variables to find any that matches
* the given string. An index to the variable_const[] array is returned,
* or -1 on failure.
*/
int get_variable(char *name) {
int i;
char *tmp=find_string(name);
for(i=0;i<NR_OF_VARIABLES;i++)
if(variables[i]==tmp)
return i;
return -1;
}
/*
* Returns a pointer to a static string which contains all variables
* which are different in the two given objects.
*/
char *get_ob_diff(object *op,object *op2) {/* I plan to optimize this heavily */
static char buf2[HUGE_BUF];
static char buf[HUGE_BUF];
int tmp;
buf[0]='\0';
if(op->name && op->name!=op2->name) {
sprintf(buf2,"name %s\n",op->name);
strcat(buf,buf2);
}
if(op->title && op->title!=op2->title) {
sprintf(buf2,"title %s\n", op->title);
strcat(buf, buf2);
}
if(op->race && op->race!=op2->race) {
sprintf(buf2,"race %s\n",op->race);
strcat(buf,buf2);
}
if(op->slaying && op->slaying!=op2->slaying) {
sprintf(buf2,"slaying %s\n",op->slaying);
strcat(buf,buf2);
}
if(op->msg && op->msg!=op2->msg) {
strcat(buf,"msg\n");
strcat(buf,op->msg);
strcat(buf,"endmsg\n");
}
if(op->other_arch!=op2->other_arch&&op->other_arch!=NULL &&
op->other_arch->name) {
sprintf(buf2,"other_arch %s\n",op->other_arch->name);
strcat(buf,buf2);
}
if(op->face!=op2->face) {
sprintf(buf2,"%s %s\n",variable_const[V_FACE],
op->face->name);
strcat(buf,buf2);
}
if(op->stats.Str!=op2->stats.Str)
save_long(buf,variable_const[V_STR],op->stats.Str);
if(op->stats.Dex!=op2->stats.Dex)
save_long(buf,variable_const[V_DEX],op->stats.Dex);
if(op->stats.Con!=op2->stats.Con)
save_long(buf,variable_const[V_CON],op->stats.Con);
if(op->stats.Wis!=op2->stats.Wis)
save_long(buf,variable_const[V_WIS],op->stats.Wis);
if(op->stats.Pow!=op2->stats.Pow)
save_long(buf,variable_const[V_POW],op->stats.Pow);
if(op->stats.Cha!=op2->stats.Cha)
save_long(buf,variable_const[V_CHA],op->stats.Cha);
if(op->stats.Int!=op2->stats.Int)
save_long(buf,variable_const[V_INT],op->stats.Int);
if(op->stats.hp!=op2->stats.hp)
save_long(buf,variable_const[V_HP],op->stats.hp);
if(op->stats.maxhp!=op2->stats.maxhp)
save_long(buf,variable_const[V_MAXHP],op->stats.maxhp);
if(op->stats.sp!=op2->stats.sp)
save_long(buf,variable_const[V_SP],op->stats.sp);
if(op->stats.maxsp!=op2->stats.maxsp)
save_long(buf,variable_const[V_MAXSP],op->stats.maxsp);
if(op->stats.grace!=op2->stats.grace)
save_long(buf,variable_const[V_GRACE],op->stats.grace);
if(op->stats.maxgrace!=op2->stats.maxgrace)
save_long(buf,variable_const[V_MAXGRACE],op->stats.maxgrace);
if(op->stats.exp!=op2->stats.exp)
save_long(buf,variable_const[V_EXP],op->stats.exp);
if(op->expmul!=op2->expmul)
save_double(buf,variable_const[V_EXPMUL],op->expmul);
if(op->stats.food!=op2->stats.food)
save_long(buf,variable_const[V_FOOD],op->stats.food);
if(op->stats.dam!=op2->stats.dam)
save_long(buf,variable_const[V_DAM],op->stats.dam);
if(op->stats.luck!=op2->stats.luck)
save_long(buf,variable_const[V_LUCK],op->stats.luck);
if(op->stats.wc!=op2->stats.wc)
save_long(buf,variable_const[V_WC],op->stats.wc);
if(op->stats.ac!=op2->stats.ac)
save_long(buf,variable_const[V_AC],op->stats.ac);
if(op->armour!=op2->armour)
save_long(buf,variable_const[V_ARMOUR],op->armour);
if(op->x!=op2->x)
save_long(buf,variable_const[V_X],op->x);
if(op->y!=op2->y)
save_long(buf,variable_const[V_Y],op->y);
if(op->speed!=op2->speed) {
sprintf(buf2,"speed %f\n",op->speed);
strcat(buf,buf2);
}
if(op->speed > 0 && op->speed_left!=op2->speed_left) {
sprintf(buf2,"speed_left %f\n",op->speed_left);
strcat(buf,buf2);
}
if(op->move_status != op2->move_status)
save_long(buf,variable_const[V_MOVE_STATUS],op->move_status);
if(op->move_type != op2->move_type)
save_long(buf,variable_const[V_ATT_MOVE],op->move_type);
if(op->nrof!=op2->nrof)
save_long(buf,variable_const[V_NROF],op->nrof);
if(op->level!=op2->level)
save_long(buf,variable_const[V_LEVEL],op->level);
if(op->direction!=op2->direction)
save_long(buf,variable_const[V_DIRECTION],op->direction);
if(op->type!=op2->type)
save_long(buf,variable_const[V_TYPE],op->type);
if(op->immune!=op2->immune)
save_long(buf,variable_const[V_IMMUNE],op->immune);
if(op->protected!=op2->protected)
save_long(buf,variable_const[V_PROTECTED],op->protected);
if(op->attacktype!=op2->attacktype)
save_long(buf,variable_const[V_ATTACKTYPE],op->attacktype);
if(op->vulnerable!=op2->vulnerable)
save_long(buf,variable_const[V_VULNERABLE],op->vulnerable);
if(op->path_attuned!=op2->path_attuned)
save_long(buf,variable_const[V_PATH_ATTUNED],op->path_attuned);
if(op->path_repelled!=op2->path_repelled)
save_long(buf,variable_const[V_PATH_REPELLED],op->path_repelled);
if(op->path_denied!=op2->path_denied)
save_long(buf,variable_const[V_PATH_DENIED],op->path_denied);
if(op->material!=op2->material)
save_long(buf,variable_const[V_MATERIAL],op->material);
if(op->value!=op2->value)
save_long(buf,variable_const[V_VALUE],op->value);
if(op->carrying!=op2->carrying)
save_long(buf,variable_const[V_CARRYING],op->carrying);
if(op->weight!=op2->weight)
save_long(buf,variable_const[V_WEIGHT],op->weight);
if(op->invisible!=op2->invisible)
save_long(buf,variable_const[V_INVISIBLE],op->invisible);
if(op->state!=op2->state)
save_long(buf,variable_const[V_STATE],op->state);
if(op->magic!=op2->magic)
save_long(buf,variable_const[V_MAGIC],op->magic);
if(op->last_heal!=op2->last_heal)
save_long(buf,variable_const[V_LAST_HEAL],op->last_heal);
if(op->last_sp!=op2->last_sp)
save_long(buf,variable_const[V_LAST_SP],op->last_sp);
if(op->last_eat!=op2->last_eat)
save_long(buf,variable_const[V_LAST_EAT],op->last_eat);
if(QUERY_FLAG(op,FLAG_IS_LINKED) && (tmp = get_button_value(op)))
save_long(buf,variable_const[V_CONNECTED],tmp);
if(op->glow_radius!=op2->glow_radius)
save_long(buf,variable_const[V_GLOW_RADIUS],op->glow_radius);
#ifdef NPC_PROG
if(op->npc_status!=op2->npc_status)
save_long(buf,variable_const[V_NPC_STATUS],op->npc_status);
if(op->npc_program!=op2->npc_program)
save_long(buf,variable_const[V_NPC_PROGRAM],op->npc_program);
#endif
#if 0
if(op->run_away!=op2->run_away)
save_long(buf,variable_const[V_EDITABLE],op->arch->editable);
#endif
/* Eneq(@csd.uu.se): Handles run_away and pick_up */
if(op->run_away!=op2->run_away)
save_long(buf,variable_const[V_RUN_AWAY],op->run_away);
if(op->pick_up!=op2->pick_up)
save_long(buf,variable_const[V_PICK_UP],op->pick_up);
/* Vick (@bern.docs.uu.se) @921107 -> Handle 'will_apply' &
'random_movement.*/
if (op->will_apply!=op2->will_apply)
save_long(buf,variable_const[V_WILL_APPLY],op->will_apply);
/* Mol(@meryl.csd.uu.se) 921108 Handle can_apply */
if (op->can_apply!=op2->can_apply)
save_long(buf,variable_const[V_CAN_APPLY],op->can_apply);
for (tmp=0; tmp <= NUM_FLAGS; tmp++) {
if ((flag_links[tmp][0]!=-1) && (QUERY_FLAG(op, flag_links[tmp][0]) !=
QUERY_FLAG(op2, flag_links[tmp][0]))) {
if (flag_links[tmp][0]==FLAG_SLOW_MOVE) {
sprintf(buf2,"%s %f\n",variable_const[V_SLOW_MOVE],SLOW_PENALTY(op));
strcat(buf,buf2);
}
else
BUFADD(QUERY_FLAG(op, flag_links[tmp][0]), flag_links[tmp][1]);
}
}
if(buf[0]=='\0')
return NULL;
return buf;
}
/*
* Dumps all variables in an object to a file.
* If bit 0 of flag is set, unpaid objects will be saved.
* If bit 1 of flag is set, don't remove the object after save.
*/
void save_object(FILE *fp,object *op, int flag) {
archetype *at;
char *cp;
object *tmp,*old;
if(op->owner!=NULL || fp == NULL)
return;
if(!(flag&1)&&(QUERY_FLAG(op, FLAG_UNPAID))) {
#if 0
remove_ob(op);
free_object(op);
#endif
return;
}
if((at=op->arch)!=NULL)
fprintf(fp,"arch %s\n",at->name);
if((cp=get_ob_diff(op,&((at==NULL?empty_archetype:at)->clone)))!=NULL)
fputs(cp,fp);
/* Eneq(@csd.uu.se): Added this to allow containers being saved with contents*/
old=NULL;
if (flag & 2 )
for(tmp=op->inv;tmp!=NULL;tmp=tmp->below)
save_object(fp,tmp,flag);
else while ((tmp=op->inv)!=NULL) {
if(old==tmp) {
LOG(llevError,"Recursive loop in inventory\n");
break;
}
save_object(fp,tmp,flag);
old=tmp;
}
if (!(flag&2)) {
remove_ob(op);
free_object (op);
}
fprintf(fp,"end\n");
}
/*
* set_variable() expects buf to be a line with two arguments, the first
* being a variable and the second being the value (which can be anything from
* an integer to a string).
* The object given will have the given variable modified.
*
* -1 will be returned if there is no such variable
* 0 will be returned if the variable is to be ignored
* 1 will be returned if the variable was "anim"
* 2 will be returned if the variable was "end"
* 3 will be returned if the variable was "Inventory"
* 4 will be returned if the variable was "More"
* 5 will be returned if the variable was "msg"
* 6 will be returned if the variable was "endmsg"
* otherwise 0 will be returned
*/
int set_variable(object *op,char *buf) {
char *vbp;
int value,tmp,var;
if((vbp=strchr(buf,'\n'))!=NULL) /* Change newline into end of string */
*vbp='\0';
else
LOG(llevDebug, "Line too long.\n");
if((vbp=strchr(buf,' '))==NULL) /* No argument to the variable */
value=0,vbp=NULL;
else {
*vbp='\0',vbp++;
value=atol(vbp);
}
switch(var=get_variable(buf)) {
case V_ARCH:
op->arch=find_archetype(vbp);
if(op->arch!=NULL)
copy_object(&op->arch->clone,op);
break;
case V_OTHER_ARCH:
op->other_arch=find_archetype(vbp);
break;
case V_RACE:
if(op->race!=NULL)
free_string(op->race);
op->race=add_string(vbp);
break;
case V_SLAYING:
if(op->slaying!=NULL)
free_string(op->slaying);
op->slaying=add_string(vbp);
break;
case V_MSG:
return 5;
case V_MSGEND:
return 6;
case V_INVENTORY:
return 3;
case V_MORE:
return 4;
case V_ANIM:
if(op->arch==NULL) {
LOG(llevError,"Got animation in object without archetype:\n");
return 0;
}
SET_FLAG(op,FLAG_ANIMATE);
return 1;
case V_END:
return 2;
case V_OBJECT:
if(vbp==NULL) {
LOG(llevError,"Object lacks name.\n");
return 0;
}
if(op->arch!=NULL)
op->arch->name=add_string(vbp);
op->name=add_string(vbp);
break;
case V_NAME:
if(*vbp=='\0') {
LOG(llevError,"name without name\n");
break;
}
if(op->name!=NULL)
free_string(op->name);
op->name=add_string(vbp);
break;
case V_TITLE:
if(*vbp=='\0') {
LOG(llevError, "title without name\n");
break;
}
if(op->title!=NULL)
free_string(op->title);
op->title = add_string(vbp);
break;
case V_SPEED:
sscanf(vbp,"%f",&op->speed);
if (op->speed<0)
op->speed_left=op->speed_left-RANDOM()%100/100.0;
update_ob_speed(op);
break;
case V_SPEED_LEFT:
sscanf(vbp,"%f",&op->speed_left);
break;
case V_SLOW_MOVE:
{
float f;
sscanf(vbp,"%f",&f);
SET_SLOW_PENALTY(op,f);
SET_FLAG(op,FLAG_SLOW_MOVE);
}
break;
/* Eneq(@csd.uu.se): Added handleof archetype-field anim_speed */
case V_ANIM_SPEED:
op->anim_speed = (unsigned char) value;
break;
/* kholland @ sunlab.cit.cornell.edu added move_type and status */
case V_ATT_MOVE:
op->move_type = (unsigned short) value;
break;
case V_MOVE_STATUS:
op->move_status = (signed long) value;
break;
/*
* Eneq(@csd.uu.se): Added handle of container <no> where no is containers
* weight limit, and no_drop which makes an item undroppable
*/
case V_CONTAINER:
op->weight_limit=(signed long) value;
break;
case V_FACE:
#if 0
op->face.number=(Fontindex)FindFace (vbp,0);
#else
op->face = &new_faces[FindFace(vbp,0)];
#endif
break;
case V_COLOR_FG:
#if 0
op->face.fg = find_color(vbp);
#else
/* LOG(llevDebug,"Got object with color set: %s\n", vbp);*/
#endif
break;
case V_COLOR_BG:
#if 0
op->face.bg = find_color(vbp);
#else
/* LOG(llevDebug,"Got object with color set: %s\n", vbp);*/
#endif
break;
case V_STR:
op->stats.Str=(signed char) value;
break;
case V_DEX:
op->stats.Dex=(signed char) value;
break;
case V_CON:
op->stats.Con=(signed char) value;
break;
case V_WIS:
op->stats.Wis=(signed char) value;
break;
case V_POW:
op->stats.Pow=(signed char) value;
break;
case V_CHA:
op->stats.Cha=(signed char) value;
break;
case V_INT:
op->stats.Int=(signed char) value;
break;
case V_HP:
op->stats.hp=(signed short) value;
break;
case V_MAXHP:
op->stats.maxhp=(signed short) value;
break;
case V_SP:
op->stats.sp=(signed short) value;
break;
case V_MAXSP:
op->stats.maxsp=(signed short) value;
break;
case V_GRACE:
op->stats.grace=(signed short) value;
break;
case V_MAXGRACE:
op->stats.maxgrace=(signed short) value;
break;
case V_EXP:
op->stats.exp=(signed long) value;
break;
case V_EXPMUL:
sscanf(vbp,"%lf",&(op->expmul));
break;
case V_FOOD:
op->stats.food=(signed short) value;
break;
case V_DAM:
op->stats.dam=(sint16) value;
break;
case V_LUCK:
op->stats.luck=(signed char) value;
break;
case V_WC:
op->stats.wc=(signed char) value;
break;
case V_AC:
op->stats.ac=(signed char) value;
break;
case V_ARMOUR:
op->armour=(signed char) value;
break;
case V_X:
op->x=(signed short) value,
op->ox=(signed short) value;
break;
case V_Y:
op->y=(signed short) value,
op->oy=(signed short) value;
break;
case V_NROF:
op->nrof=(unsigned long) value;
break;
case V_LEVEL:
op->level=(signed char) value;
break;
case V_DIRECTION:
op->direction=(signed char) value;
break;
case V_TYPE:
op->type=(unsigned char) value;
break;
case V_IMMUNE:
op->immune=(unsigned int) value;
break;
case V_PROTECTED:
op->protected=(unsigned int) value;
break;
case V_ATTACKTYPE:
op->attacktype=(unsigned int) value;
break;
case V_VULNERABLE:
op->vulnerable=(unsigned int) value;
break;
case V_PATH_ATTUNED:
op->path_attuned=(uint32) value;
break;
case V_PATH_REPELLED:
op->path_repelled=(uint32) value;
break;
case V_PATH_DENIED:
op->path_denied=(uint32) value;
break;
case V_MATERIAL:
op->material=(uint16) value;
break;
case V_VALUE:
op->value=(signed long) value;
break;
case V_CARRYING:
op->carrying=(signed long) value;
break;
case V_WEIGHT:
op->weight=(signed long) value;
break;
case V_INVISIBLE:
op->invisible=(signed short) value;
break;
case V_MAGIC:
op->magic=(unsigned char) value;
break;
case V_STATE:
op->state=(unsigned char) value;
break;
case V_LAST_HEAL:
op->last_heal=(signed short) value;
break;
case V_LAST_SP:
op->last_sp=(signed short) value;
break;
case V_LAST_EAT:
op->last_eat=(signed short) value;
break;
case V_CONNECTED:
add_button_link(op, op->map, value);
break;
#ifdef NPC_PROG
case V_NPC_STATUS:
op->npc_status=(unsigned short) value;
break;
case V_NPC_PROGRAM:
op->npc_program=(unsigned short) value;
break;
#endif
case V_EDITABLE:
op->arch->editable = value;
break;
/* Eneq(@csd.uu.se): Handle PICK_UP */
case V_PICK_UP:
op->pick_up=(unsigned char) value;
break;
/* Eneq(@csd.uu.se): Handle RUN_AWAY, (CAN_)PASS_THRU. */
case V_RUN_AWAY:
op->run_away = (unsigned short) value;
break;
/* Vick's (vick@bern.docs.uu.se) patch 921107 : will_apply, which
enables a monster to apply things on the ground. */
case V_WILL_APPLY:
op->will_apply = (unsigned char) value;
break;
case V_GLOW_RADIUS:
op->glow_radius = (signed short) value;
break;
/* Note: With the new FLAG value method, most all of these bits are
* set in the default area. The only ones not set there are
* special cases (those needing to check the object, print debugging
* messages, or SET/CLEAR multiple flags.
*/
case V_WIZ:
if (value) {
SET_FLAG(op, FLAG_WIZ);
SET_FLAG(op, FLAG_WAS_WIZ);
SET_FLAG(op, FLAG_WIZPASS);
}
else {
CLEAR_FLAG(op, FLAG_WIZ);
CLEAR_FLAG(op, FLAG_WIZPASS);
}
break;
/* Mol(@csd.docs.uu.se) patch 921108 : can_apply, is similair to will_apply,
but applies thing it has picked up. */
case V_CAN_APPLY:
op->can_apply = (unsigned char) value;
break;
case V_FRIENDLY:
if(value) {
SET_FLAG(op,FLAG_FRIENDLY);
if (op->type != PLAYER) {
LOG(llevDebug, "Adding friendly object %s.\n",op->name);
add_friendly_object(op);
}
}
else
CLEAR_FLAG(op,FLAG_FRIENDLY);
break;
case V_IDENTIFIED:
if(value) {
SET_FLAG(op,FLAG_IDENTIFIED);
CLEAR_FLAG(op, FLAG_KNOWN_MAGICAL);
}
else
CLEAR_FLAG(op,FLAG_IDENTIFIED);
break;
case V_WAS_WIZ:
if(value)
SET_FLAG(op,FLAG_WAS_WIZ);
else
CLEAR_FLAG(op,FLAG_WAS_WIZ);
break;
/* In the default statement, it will handle all cases above.
* First search through the flag_links, to match corresponding
* variables. IF it doesn't find anything, then to the check for
* randomitems, and then print the error messages.
*/
default:
for (tmp=0; tmp<=NUM_FLAGS; tmp++) {
if (flag_links[tmp][1]==var) {
if (value) SET_FLAG(op, flag_links[tmp][0]);
else CLEAR_FLAG(op, flag_links[tmp][0]);
return 0;
}
}
if(!strcmp(buf,"randomitems"))
return 0;
sprintf(errmsg,"Warning, unknown (or oldfashioned) variable: %s",buf);
return -1;
}
return 0;
}
/*
* Loads an object from the given file-pointer.
* Variables will be read and parsed and patched into the object
* until the string "end" is reached, or the end of the file.
* If EOF is reached, it returnes false, otherwise true.
*/
int load_object(FILE *fp, object *op) {
char buf[MAX_BUF];
char msgbuf[HUGE_BUF];
Fontindex faces[MAX_ANIMATIONS];
int position=1; /* 1 = standalone, 2 = inventory, 3 = head/tail link */
int anim_start=0,msg_start=0;
object *tmp;
buf[MAX_BUF - 1] = '\0';
while(fgets(buf,sizeof(buf),fp)!=NULL) {
if(*buf=='#')
continue;
if(anim_start) {
if(!strncmp("mina",buf,4)) {
op->arch->animations=anim_start-1,anim_start=0;
op->arch->faces = (Fontindex *) malloc
(sizeof(Fontindex) * (op->arch->animations+1));
memcpy((void *)op->arch->faces,(void *)faces,
(op->arch->animations+1)*sizeof(Fontindex));
} else {
faces[anim_start - 1] = FindFace(buf,0);
anim_start++;
}
continue;
}
if(msg_start&&strncmp(buf,"endmsg",6)) {
strcat(msgbuf,buf);
continue;
}
/* found an arch in the object. Must be part of the
* objects inventory.
*/
if(!strncmp(buf,"arch ",5)&&op->arch!=NULL) {
object *otmp;
tmp=get_object();
set_variable(tmp, buf);
load_object(fp, tmp);
if (op->inv!=NULL) {
for (otmp=op->inv; otmp->below!=NULL; otmp=otmp->below);
otmp->below=tmp;
}
else op->inv=tmp;
return load_object (fp, op);
}
switch(set_variable(op,buf)) {
case -1:
LOG(llevError,"%s\n",errmsg);
break;
case 1:
anim_start=1;
break;
case 2:
return position;
case 3:
position=2;
break;
case 4:
position=3;
break;
case 5:
msg_start=1;
msgbuf[0]='\0';
break;
case 6:
msg_start=0;
op->msg=add_string(msgbuf);
if (strlen(op->msg) > 500)
LOG(llevDebug, "message: %d\n", strlen(op->msg));
break;
}
}
return 0;
}
/*
* Loads an object from the given file-pointer.
* Variables will be read and parsed and patched into the object
* until the string "end" is reached, or the end of the file.
* If EOF is reached, it returnes false, otherwise true.
*/
enum LoadState { unknown, arch, anim, message };
object *LoadObject (FILE *fp, char *inbuf) {
char buf[256];
char msgbuf[HUGE_BUF];
Fontindex faces[MAX_ANIMATIONS];
int anim_start = 0;
object *op = NULL;
enum LoadState state = unknown;
if (inbuf!=NULL) {
if (strncmp("arch", inbuf, 4))
LOG (llevError, "parse error in inbuf: %s\n (expecting arch)", inbuf);
else {
state = arch;
op = get_object();
set_variable (op, inbuf);
}
}
while(fgets(buf,sizeof(buf),fp)!=NULL) {
if(*buf=='#')
continue;
switch (state) {
case unknown:
if (strncmp ("arch", buf, 4))
LOG (llevError, "parse error in: %s\n (expecting arch)", buf);
else {
state = arch;
op = get_object();
set_variable (op, buf);
}
break;
case arch:
if(!strncmp (buf, "arch ", 5)) {
object *tmp;
tmp = LoadObject(fp,buf);
(void) insert_ob_in_ob (tmp, op);
break;
}
switch(set_variable (op, buf)) {
case -1:
LOG(llevError,"%s\n",errmsg);
break;
case 0:
break;
case 1:
state = anim;
anim_start = 0;
break;
case 2:
return op;
case 5:
state = message;
msgbuf[0] = '\0';
break;
default:
LOG(llevError,"LoadObject()\n");
break;
}
break;
case anim:
if(!strncmp ("mina", buf, 4)) {
op->arch->animations = anim_start;
op->arch->faces = (Fontindex *) malloc (sizeof (Fontindex) * anim_start);
memcpy(op->arch->faces, faces, anim_start * sizeof (Fontindex));
state = arch;
break;
}
faces[anim_start++] = FindFace(buf,0);
break;
case message:
if(!strncmp (buf, "endmsg", 6)) {
op->msg = add_string (msgbuf);
state = arch;
break;
}
strcat(msgbuf,buf);
}
}
if (op)
free_object (op);
return NULL;
}